Manipulating data in VFBitmaps

Beginning with VirtualDub 1.2, it is possible to access VirtualDub's bitmap manipulation functions from external video filters.  These perform a number of useful tasks such as rectangle fills, color translation, bitmap format conversions, and stretch blits.  These routines are quite fast and can save you development time.


Avisynth does not support any of the VFBitmap functions that process image data, and will likely throw an error if you call any of the functions that are marked virtual.

Initializing vtable support

VFBitmap functions are virtual, and VirtualDub uses a bit of a hack to allow external video filters to create VFBitmaps, which requires initializing vtable pointers.  To gain access to the VFBitmap vtable pointers, place

#define VDEXT_VIDEO_FILTER
#define VDEXT_MAIN

or

#define VDEXT_VIDEO_FILTER
#define VDEXT_NOTMAIN

at the top of each module.  The file defining VDEXT_MAIN will declare the global variables, and the files defining VDEXT_NOTMAIN will extern them.  Then, in your module initializing function, add the following line:

INITIALIZE_VTBLS;

This initializes the vtable support.  After this point, you can initialize VFBitmap objects.  This necessarily means you cannot declare global VFBitmaps.  Because of the way VirtualDub treats module data, you also cannot declare VFBitmaps directly in a module data structure:

typedef struct MyFilterData {
    VFBitmap tempbm;  // this will cause page faults
} MyFilterData;

You can, however, use a pointer to a data structure that you allocate, which has an embedded VFBitmap.

VFBitmap pixel formats

Different VFBitmap functions work on 8, 16, 24, and 32-bit bitmaps.  Here is how they are defined:

depth Layout in a dword R mask G mask B mask Description
8
  C
N/A N/A N/A 8-bit paletted format
16
    R G B
0x7c00 0x03e0 0x001f 5-5-5 (16-bit) BGR
16
  R G B
0xf800 0x07e0 0x001f 5-6-5 (16-bit) BGR (seldom used)
24
  R G B
0xff0000 0x00ff00 0x0000ff 24-bit BGR format
32
  R G B
0x00ff0000 0x0000ff00 0x000000ff 32-bit BGRA format

All pixel formats are supported by Window GDI and the DirectDraw HEL, so bitmap data is interchangeable between VirtualDub and the various Windows APIs.  The brunt of most VirtualDub video filter work is done in 32-bit, but you may find the various conversion functions useful.  They are significantly faster than the 16-bit GDI in Windows 95/98.

Notice that 16-bit 565 RGB has the same depth value as 16-bit 555 RGB.  The 565 format is only supported by a few functions, and by default depth==16 implies the 555 format.

VFBitmap functions

The VFBitmap functions are all virtual member functions, and so they are invoked as part of the bitmap objects.

Address32()

Pixel *Address32(PixCoord x, PixCoord y) const;

Returns the address of a particular pixel in the bitmap, with normal y coordinates.

Inputs:
    x,y: coordinates of the desired pixel

Returns:
    Address of the pixel at (x,y)

Address32i()

Pixel *Address32i(PixCoord x, PixCoord y) const;

Returns the address of a particular pixel in the bitmap, with inverted y coordinates.

Inputs:
    x: x-coordinate of the desired pixel
	y: inverted y-coordinate of the desired pixel

Returns:
	Address of the pixel at (x, h-y-1)

PitchAlign4()

PixOffset PitchAlign4();

Computes a dword-aligned pitch value for the current width and bit depth.

Returns:
    Scanline pitch for current width and bit depth, rounded up to next 4 bytes

PitchAlign8()

PixOffset PitchAlign8();

Computes a qword-aligned pitch value for the current width and bit depth.

Returns:
    Scanline pitch for current width and bit depth, rounded up to next 8 bytes

Modulo()

PixOffset Modulo();

Computes the gap between scanlines from the current pitch, width, and bit depth.

Returns:
    Gap between scanlines, in bytes

Size()

PixOffset Size();

Computes the total number of bytes the bitmap occupies in memory.

Returns:
    Total number of bytes bitmap occupies

init(data, w, h, depth)

VBitmap& init(void *data, PixDim w, PixDim h, int depth) throw();

Initializes a VFBitmap with the given bitmap structure and memory area.

Inputs:
    data:   pointer to bitmap memory block
    w,h:    dimensions of bitmap
    depth:  pixel depth of bitmap, in bits

Returns:
    pointer to this VFBitmap

init(data, pBitmapInfoHeader)

VBitmap& init(void *data, BITMAPINFOHEADER *pBitmapInfoHeader) throw();

Initializes a VFBitmap with the given bitmap structure and memory area.

Inputs:
    data:               pointer to bitmap memory block
	pBitmapInfoHeader:  pointer to Win32 bitmap description

Returns:
    pointer to this VFBitmap

MakeBitmapHeader(pBitmapInfoHeader)

void MakeBitmapHeader(BITMAPINFOHEADER *pBitmapInfoHeader) const throw();

Creates a Win32 bitmap description from a VFBitmap.

Inputs:
    pBitmapInfoHeader:  pointer to Win32 bitmap desc. to be filled in

Win32 BITMAPINFOHEADER structures do not allow for padding, so MakeBitmapHeader() adjusts the bitmap width to compensate.  This may require manual clipping on the GDI side.

AlignTo4()

void AlignTo4() throw();

Computes and sets the pitch, modulo, and size members of a VFBitmap for 4-byte alignment.

AlignTo8()

void AlignTo8() throw();

Computes and sets the pitch, modulo, and size members of a VFBitmap for 8-byte alignment.

BitBlt()

void BitBlt(PixCoord x2, PixCoord y2, const VBitmap *src, PixCoord x1,
        PixCoord y1, PixDim dx, PixDim dy) const throw();

Copies a rectangular region from one bitmap to another.

Inputs:
    x2,y2:  top left corner of destination rectangle
    x1,y1:  top left corner of source rectangle
    src:    source bitmap
    dx,dy:  dimensions of rectangle to be copied
            -1, -1 to copy largest possible rectangle

BitBlt() can do format conversion between 16, 24, and 32 bit deep bitmaps.  It will also convert 8-bit paletted bitmaps to 16-, 24-, and 32-bit bitmaps.

BitBltDither()

void BitBltDither(PixCoord x2, PixCoord y2, const VBitmap *src, PixDim x1,
        PixDim y1, PixDim dx, PixDim dy, bool to565) const throw();

Dithers a 32-bit deep bitmap down to 15- or 16-bit RGB.

Inputs:
    x2,y2:  top left corner of destination rectangle
    x1,y1:  top left corner of source rectangle
    src:    source bitmap
    dx,dy:  dimensions of rectangle to be copied
            -1, -1 to copy largest possible rectangle

BitBltDither() uses a 4x4 ordered dither matrix.  Images dithered using this routine may appear slightly darker than with BitBlt().

BitBlt565()

void BitBlt565(PixCoord x2, PixCoord y2, const VBitmap *src, PixDim x1,
        PixDim y1, PixDim dx, PixDim dy) const throw();

Copies a rectangular region from a 32-bit bitmap to a 16-bit 565 bitmap.

Inputs:
    x2,y2:  top left corner of destination rectangle
    x1,y1:  top left corner of source rectangle
    src:    source bitmap
    dx,dy:  dimensions of rectangle to be copied
            -1, -1 to copy largest possible rectangle

BitBltXlat1()

bool BitBltXlat1(PixCoord x2, PixCoord y2, const VBitmap *src, PixCoord x1,
        PixCoord y1, PixDim dx, PixDim dy, const Pixel8 *tbl) const throw();

Translates a rectangular region from one 32-bit bitmap to another with a
single lookup table for all channels.

Inputs:
    x2,y2:  top left corner of destination rectangle
    x1,y1:  top left corner of source rectangle
    src:    source bitmap
    dx,dy:  dimensions of rectangle to be translated
            -1, -1 to translate largest possible rectangle
    tbl:    256-byte lookup table used to translate pixels

BitBltXlat1() takes each of the three RGB channels in each pixel and runs it through the given lookup table.  This allows you to do simple monochromatic effects such as brightness, contrast, and gamma correction.

BitBltXlat3()

bool BitBltXlat3(PixCoord x2, PixCoord y2, const VBitmap *src, PixCoord x1,
        PixCoord y1, PixDim dx, PixDim dy, const Pixel32 *tbl) const throw();

Translates a rectangular region from one 32-bit bitmap to another with a
separate lookup table for all channels.

Inputs:
    x2,y2:  top left corner of destination rectangle
    x1,y1:  top left corner of source rectangle
    src:    source bitmap
    dx,dy:  dimensions of rectangle to be translated
            -1, -1 to translate largest possible rectangle
    tbl:    1K-lookup table used to translate pixels

BitBltXlat3() is similar to BitBltXlat1() except that each RGB channel has its own lookup table, allowing you to use separate color ramps.  The three tables are interleaved together in a 256 dword entry table in pixel format (0x00rrggbb).

StretchBltNearestFast()

bool StretchBltNearestFast(PixCoord x1, PixCoord y1, PixDim dx, PixDim dy,
        const VBitmap *src, double x2, double y2, double dx1, double dy1)
        const throw();

Stretches a region from one 32-bit bitmap to another using nearest neighbor
sampling.

Inputs:
    x1, y1, dx, dy:    position and dimensions of destination rectangle
    x2, y2, dx2, dy2:  position and dimensions of source rectangle
    src:               source bitmap

StretchBltNearestFast() will not clip either the source or destination regions and will return false if any of the regions exceed their bitmaps.  You can flip the source region horizontally and vertically by making dx2 and/or dy2 negative.  With horizontal flips, x2 becomes the right side of the rectangle, and with vertical flips, y2 is the bottom.

StretchBltBilinearFast()

bool StretchBltBilinearFast(PixCoord x1, PixCoord y1, PixDim dx, PixDim dy,
        const VBitmap *src, double x2, double y2, double dx1, double dy1)
        const throw();

Stretches a region from one 32-bit bitmap to another using bilinear sampling.

Inputs:
    x1, y1, dx, dy:    position and dimensions of destination rectangle
    x2, y2, dx2, dy2:  position and dimensions of source rectangle
    src:               source bitmap

StretchBltBilinearFast() will not clip either the source or destination regions and will return false if any of the regions exceed their bitmaps.  You can flip the source region horizontally and vertically by making dx2 and/or dy2 negative.  With horizontal flips, x2 becomes the right side of the rectangle, and with vertical flips, y2 is the bottom.  StretchBltBilinearFast() always uses a 2x2 source pixel block and will give suboptimal results on shrink operations.

RectFill()

bool RectFill(PixCoord x1, PixCoord y1, PixDim dx, PixDim dy, Pixel32 c)
        const throw();

Fills a rectangular region in a 32-bit bitmap with a solid color.

Inputs:
    x, y:            top left corner of rectangle
    dx, dy:          dimensions of rectangle
            -1, -1 to translate largest possible rectangle
    c:               color to fill with

Histogram()

bool Histogram(PixCoord x, PixCoord y, PixCoord dx, PixCoord dy, long
        *pHisto, int iHistoType) const throw();

Creates a histogram from pixels in a given source rectangle of a 16-, 24-,
or 32-bit bitmap.

Inputs:
    x, y:            top left corner of rectangle
    dx, dy:          dimensions of rectangle
            -1, -1 to translate largest possible rectangle
    pHisto:          pointer to 256-entry histogram array to be modified
    iHistoType:      one of these values, to specify histogram type:
          HISTO_LUMA     luminance channel (21%/71%/7%)
          HISTO_GRAY     red, green, and blue
          HISTO_RED      red channel only
          HISTO_GREEN    green channel only
          HISTO_BLUE     blue channel only

Histogram() does not clear the histogram array, so you must reset it to all zero beforehand.  You can also clear it once, and then call Histogram() multiple times to combine the results from several regions.  In all cases except HISTO_GRAY, a value from 0-255 is added to pHisto[i] for each pixel.  With HISTO_GRAY, because channel values range 0-255, values 0-765 can be added per pixel.

[up] back to main page


VirtualDub external filter SDK 1.05©1999-2001 Avery Lee <phaeron@virtualdub.org>